package com.ruoyi.central.utils.pojo;

import com.ruoyi.central.controller.vo.AreaVo;
import com.ruoyi.central.domain.*;
import com.ruoyi.central.enums.AreaTypeEnum;
import com.ruoyi.central.enums.MaterialStatusEnum;
import com.ruoyi.central.service.*;
import com.ruoyi.common.utils.CollectionUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.EnumUtils;
import com.ruoyi.common.utils.collection.Lists;
import com.ruoyi.common.utils.service.ServiceUtils;
import com.ruoyi.common.utils.spring.SpringUtils;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Classname OperationStationUtils
 * @Author: sunluquan
 * @Date: 2022/5/8 18:08
 * @Description TODO
 * 操作站位相关数据获取的工具类
 */
public class OperationStationUtils {

    private final static ITopCentralOperationStationService operationStationService;

    private final static ITopCentralMaterialService materialService ;

    private final static ITopCentralArtProcessRunService artProcessRunService ;

    private final static ITopCentralOperationStationMaterialService operationStationMaterialService ;

    private final static ITopCentralAreaService areaService ;
    
    private final static ITopCentralProcessStepRunService processStepRunService ;

    private final static <T> T getBean(Class<T> clazz){
        return SpringUtils.getBean(clazz);
    }

    static{
        operationStationService =getBean(ITopCentralOperationStationService.class);
        materialService =getBean(ITopCentralMaterialService.class);
        artProcessRunService =getBean(ITopCentralArtProcessRunService.class);
        operationStationMaterialService =getBean(ITopCentralOperationStationMaterialService.class);
        areaService =getBean(ITopCentralAreaService.class);
        processStepRunService = getBean(ITopCentralProcessStepRunService.class);
    }
    /**
     * 获取操作工位与零件关系对象集合
     * 1.获取所有操作工位与物料关系对象
     * 2.获取所有的物料对象 再根据 ‘操作工位与物料关系对象’ 过滤出与操作工位绑定的物料对象
     * 3.根据物料编号获取 执行的工艺对象
     * 4.根据执行的工艺对象获取 执行的工序对象
     * 5.将物料填充至 ---》操作工位与物料关系对象
     * @return
     */
    public static Collection<TopCentralOperationStationMaterial> getTopCentralOperationStationMaterialList(){
        //物料当前所在工位
        Collection<TopCentralOperationStationMaterial> operationStationMaterials = operationStationMaterialService.selectAllMap().values();

        if(StringUtils.isEmpty(operationStationMaterials)){
            return operationStationMaterials;
        }
        Map<String, TopCentralOperationStationMaterial> operationStationMaterialMap = CollectionUtils.toMap(operationStationMaterials, TopCentralOperationStationMaterial::getMaterialId);
        TopCentralMaterial materialOfParams = new TopCentralMaterial();
        materialOfParams.setMaterialStatus(MaterialStatusEnum.USE_OF_STATUS.getValue());
        List<TopCentralMaterial> materials = materialService.selectList(materialOfParams);
  
        //将物料对象填充至 物料-站位 关联对象中去
        for (TopCentralMaterial material : materials) {
            String materialId = material.getId();
            if(operationStationMaterialMap.containsKey(materialId)){
                operationStationMaterialMap.get(materialId).setMaterial(material);
            }
            
        }
        
        //获取所有使用中的物料 的 工艺对象
        List<TopCentralArtProcessRun> artProcessRuns = artProcessRunService.selectByProdIds(CollectionUtils.mapToList(materials,TopCentralMaterial::getId));
        //TODO 获取执行工序对象 任务状态为执行中的
        List<Integer> artProcessRunIds = CollectionUtils.mapToList(artProcessRuns, TopCentralArtProcessRun::getId);
        //获取任务状态为执行中的执行工序对象
        Map<Integer, TopCentralProcessStepRun> processStepRunMapOfExecution = processStepRunService.selectByArtProcessRunIds(artProcessRunIds);

        CollectionUtils.businessOperation(artProcessRuns,
                //将执行工序对象 填充到 工艺执行对象中
                artProcessRun->artProcessRun.setProcessStepRun(processStepRunMapOfExecution.get(artProcessRun.getId())),
                //将执行工艺对象 填充到 物料-站位 对象中去
                artProcessRun->{
                    String materialId = artProcessRun.getProdId();
                    if(operationStationMaterialMap.containsKey(materialId)){
                        operationStationMaterialMap.get(materialId).getMaterial().setArtProcessRun(artProcessRun);
                    }
                }
        );

        return operationStationMaterials;
    }
    /**
     * 获取区域列表
     * 将未分组的和分组的操作站位添加导区域列表中
     * @return
     */
    public static List<AreaVo> getOperationStationList(AreaTypeEnum areaTypeEnum){

        Map<? extends Serializable, TopCentralOperationStation> operationStationMap = operationStationService.selectAllMap();

        if(StringUtils.isNotNull(areaTypeEnum)){
            Map<? extends Serializable, TopCentralArea> topCentralAreaMap = areaService.selectAllMap();
            operationStationMap = CollectionUtils.toMap(operationStationMap.values().stream().filter(item->EnumUtils.equals(areaTypeEnum,topCentralAreaMap.get(item.getAreaId()).getType())).collect(Collectors.toList()),TopCentralOperationStation::getId);
        }

        Collection<TopCentralOperationStationMaterial> topCentralOperationStationMaterialList = getTopCentralOperationStationMaterialList();

        for (TopCentralOperationStationMaterial topCentralOperationStationMaterial : topCentralOperationStationMaterialList) {
            operationStationMap.get(topCentralOperationStationMaterial.getOperationStationId()).setOperationStationMaterial(topCentralOperationStationMaterial);
        }

        Collection<TopCentralOperationStation> operationStations = operationStationMap.values();

        ServiceUtils.complete(operationStations,areaService,(areaMap, item)->item.setArea(areaMap.get(item.getAreaId())));

        List<AreaVo> areaVos = new ArrayList<>();

        Map<Integer, List<TopCentralOperationStation>> groupOperationStationMap = new HashMap<>();

        for (TopCentralOperationStation operationStation : operationStations) {
            Integer groupId = operationStation.getGroupId();
            if(StringUtils.isNotNull(groupId)){
                if(groupOperationStationMap.containsKey(groupId)){
                    groupOperationStationMap.get(groupId).add(operationStation);
                }else{
                    groupOperationStationMap.put(groupId, Lists.newArrayList(operationStation));
                }
            }else{
                areaVos.add(AreaVo.build(Lists.newArrayList(operationStation)));
            }
        }
        CollectionUtils.businessOperation(groupOperationStationMap.values(),groupOperationStations->areaVos.add(AreaVo.build(groupOperationStations)));

        areaVos.sort(Comparator.comparing(AreaVo::getWeight));

        return areaVos;
    }

    public static List<AreaVo> getOperationStationList(){
        return getOperationStationList(null);
    }
}
